home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX504A / SECT.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  26.6 KB  |  1,085 lines

  1. /* sect.c */
  2.  
  3. /* 
  4.  * Aug-23-88 jye. Change and add codes so that can be used for MS-DOS
  5.  * Dec-20-89 jye. Free a bug that HDX gives a error message when CD-ROM 
  6.  *                  is busy. 
  7.  * Feb-11-93 jye. changed the size of the 'sentdate' buff to 56 bytes 
  8.  *                  for the 'inquiry', this will fit some hard drives. (Ex.
  9.  *                  IBM OME 0663E15)
  10.  * May-10-93 jye. Fix a bug that can't format or partition any externally
  11.  *                  connected SCSI drive if the Falcon has no internal hard-
  12.  *                  disk. Added codes in rescan()
  13.  * May-25-93 jye. Added code to check if it is removabel drive, then send the
  14.  *                  'mdsense' commend with page code 0x2e and allocation length
  15.  *                  42 to unlock the floptical drive.
  16.  * Jul-15-93 jye. Fixed a bug that didn't set the flag for the scsi drive in the
  17.  *                   MEGA STE computer.
  18.  * Jul-23-93 jye. Fixed a bug that if some type of errors occor, the scan would
  19.  *                  stop.
  20.  */
  21.  
  22. #include "obdefs.h"
  23. #include "osbind.h"
  24. #include "mydefs.h"
  25. #include "part.h"
  26. #include "hdx.h"
  27. #include "addr.h"
  28. #include "myerror.h"
  29.  
  30. #define    ZBUFSIZ    0x4000        /* about 16k == 32 sectors */
  31. #define    ZCOUNT    (ZBUFSIZ/0x200)    /* ZCOUNT = 32 */
  32. #define MAXUNITS 16            /* max number of logical units */
  33.  
  34. #define PUNINFO struct _punifno
  35. PUNINFO {
  36.         WORD puns;    /* number of physical units */
  37.         BYTE pun[MAXUNITS];
  38.         LONG partition_start[MAXUNITS]; /* offset to partition on */
  39.                                         /* physical unit */
  40. };
  41. extern long ostack;        /* old stack pointer */
  42. extern UWORD errcode();        /* function to return error code */
  43. extern int yesscan;        /* the flag for the func. IBMGPART use */
  44. extern long sptrk;        /* the sector per track */
  45. extern int npart;        /* the number of partitions */
  46. extern int ext;            /* the index of extended partition */
  47. extern int extend;        /* the index of end extended partition */
  48. extern int showmany;    /* the flag for show the too many device alert box */
  49. extern char ttscsi;        /* the flag for SCSI if set */
  50. extern char spscsixst;    /* set for the sparrow scsi exist */
  51. extern int needscan;    /* TRUE: if it is the first time to scan the units */
  52. extern int athead;        /* the # of data heads on the AT drive */
  53. extern int atcyl;        /* the # of cylinders on the AT drive */
  54. extern int atspt;        /* the # of sectors per track on the AT drive */
  55. extern int noacsi;        /* set for no ACSI drive in the system */
  56. extern char slwacsi;    /* 1: set for slow acsi device */
  57. extern char *drvid[];    /* for the id of the devices */
  58. /*
  59.  * Logical-to-dev+partition mapping table.
  60.  */
  61. int nlogdevs;                /* # logical devices */
  62. LOGMAP logmap[EXTRALOGD];    /* logical dev map */
  63. int livedevs[MAXPHYSDEVS];    /* live devs flags; 1: device is alive */
  64. int idevs[16];                /* the devs have id flags; 1: device has id */
  65. int typedev = 0x0000;        /* if set, driver is a removable driver */
  66. int typedrv = 0x0000;        /* if set, driver is a SCSI driver */
  67. int atexst;                    /* AT drive exists */
  68. int slvexst;                /* AT slave drive exists */
  69. char useblit;                /* set for it is not the stbook drive */
  70.  
  71.  
  72. /*
  73.  * Rebuild logical-to-physical mapping
  74.  * by reading and interpreting the root
  75.  * blocks for all physical devs.
  76.  *
  77.  */
  78.  
  79. rescan(flag, fnp)
  80.  
  81. int flag;    /* 0: don't report medium change error; */
  82.             /* non-0: report medium change error; */
  83. int fnp;    /* 0: do zero & markbad; 1: do format & ship; 2: do part */
  84.  
  85. {
  86.     int dev, scan=0;
  87.     char buf[512];
  88.     char sendata[56];
  89.     int partno, ret, inqret, i;
  90.     PART *partinfo;
  91.     char mask = 0x80;    /* 7th bit is set on */
  92.     int setmask;
  93.     int maxloop;
  94.  
  95.     noacsi = 1;                /* assume there is no ACSI in the system */
  96.     ostack = Super(NULL);    /* set supervice mode */
  97.  
  98.     ttscsi = chkscsi();        /* check if SCSI exists */
  99.     spscsixst = chksp();    /* check if sparrow scsi exists */
  100.     delay();
  101.     if ((atexst = chkide()))    { /* AT drive exist */
  102.         if (stbook())    {
  103.             useblit = 0;
  104.         } else {
  105.             useblit = chkblit();
  106.         }
  107.         if ((ret = identify(16, buf)) == OK)    {
  108.             delay();
  109.             /* in byte 54 of the buf having the drive's id */
  110.             gdrvid(16, &buf[54], drvid[16]);
  111.             /* return the number of cylinder, head, spt */
  112.             gparmfc(&atcyl, &athead, &atspt, buf);
  113.         } else { 
  114.             if (ret == -1)    { /* May-10-93: fix a bug by adding these codes */
  115.                 /* The bug is when Falcon without a ide drive, it will return
  116.                    a timeout, so now I will continue the process instead of 
  117.                    tread it as a error */
  118.                 drvid[16] = drvid[18];
  119.                 goto jjj;
  120.             }
  121.             delay();
  122.             Super(ostack);
  123.             ret = errcode(16);
  124.             if (tsterr(ret) != OK) 
  125.                 return ERROR;
  126.             return (-3);    /* don't have to show the alert box */
  127.         }
  128.     }
  129. jjj:
  130.     delay();
  131.     /*    Now the hardware doesn't support the slave drive, so comment it out
  132.     if ((atexst) && (slvexst = slave()))    {  AT slave drive exist 
  133.         if ((ret = identify(17, buf)) == OK)    {
  134.             atscyl = getword(buf+2);
  135.             atshead = getword(buf+6);
  136.             atsspt = getword(buf+12);
  137.             delay();
  138.         } else { 
  139.             delay();
  140.             Super(ostack);
  141.             ret = errcode(17);
  142.             if (tsterr(ret) != OK) 
  143.                 return ERROR;
  144.             return (-3);    don't have to show the alert box
  145.         }
  146.     }
  147.     */
  148.     delay();
  149.     Super(ostack);
  150.     /* set the scent message box */
  151.     if ((needscan) && ((ttscsi)||(spscsixst)))
  152.         dsplymsg(scanmsg);
  153.  
  154.     /* disable all logical and physical devs */
  155.     for (dev = 0; dev < EXTRALOGD; ++dev)
  156.         logmap[dev].lm_physdev = -1;
  157.  
  158.     for (dev = 0; dev < MAXPHYSDEVS; ++dev)
  159.         livedevs[dev] = 0;
  160.  
  161.     /* set all devices have no id */
  162.     for(i=0; i < 16; i++)    {
  163.         idevs[i] = 0;
  164.     }
  165.  
  166.     /*
  167.      * Scan all physical devs
  168.      * and pick up partition structures.
  169.      */
  170.     nlogdevs = 0;
  171.     showmany = 0;
  172.     slwacsi = 0;
  173.     if (atexst)    {
  174.         maxloop = 18;
  175.         dev = 16;
  176.     } else if ((ttscsi)||(spscsixst))    {
  177.         if (spscsixst)    {
  178.             slwacsi = 1;
  179.         } 
  180.         maxloop = 16;
  181.         dev = 8;
  182.     } else {
  183.         maxloop = 8;
  184.         slwacsi = 1;
  185.         dev = 0;
  186.     }
  187. rerescan:
  188.     for (; dev < maxloop; ++dev)
  189.     {
  190.  
  191.         if (((dev == 16) && atexst) || ((dev == 17) && slvexst))    {
  192.             if ((ret = getroot(dev, buf, (SECTOR)0)) != 0)    {
  193.                 if (ret == -1)    { /* May-10-93: to fix a bug that can't format
  194.                                      in the Falcon without a ide drive */
  195.                     /* it is timeout or without a ide drive in Falcon */
  196.                     goto noidedr;
  197.                 }
  198.                 if (tsterr(ret) != OK)    
  199.                     err(rootread);
  200.                 slwacsi = 0;
  201.                 return(ERROR);
  202.             }
  203.             goto atst;    /* skip and do the at stuff only */
  204.         }
  205.         /* initialize the buffer */
  206.         for (i = 0; i < 56; i++)        {
  207.             sendata[i] = 0;
  208.         }
  209.  
  210.         /* check see the drive is a what kind of drive */
  211.            ostack = Super(NULL);
  212.            delay();
  213.         if ((inqret = inquiry(dev, (WORD)56, sendata)) != ERROR)    {
  214.             for (i=8; i < 56; i++)    {
  215.                 if (sendata[i])    {
  216.                     break;
  217.                 }
  218.             }
  219.             if (i < 56)    {    /* there are some date return */
  220.                 gdrvid(dev, &sendata[8], drvid[dev]);
  221.                 idevs[dev] = 1;
  222.             }
  223.         }
  224.            delay();
  225.            Super(ostack);
  226.         setmask = 0x0001;
  227.         if (inqret & 0x08)    { /* the device is busy */
  228.             continue;
  229.         }
  230.         /* ret not equal OK, it may be a regular hard drive */
  231.         if ((inqret == OK)||(inqret == 7)) { /*it is not a regular hard drive*/
  232.             if (sendata[0])      {    /* it is not a hard drive */
  233.                 continue;
  234.             } else if (sendata[1] & mask)    { /* it is a removable drive */
  235.                    ostack = Super(NULL);
  236.                    delay();
  237.                 mdsense(dev, 0x2e, 0, 42, buf);    /* unlock the floptical drive */
  238.                    delay();
  239.                    Super(ostack);
  240.                 if (spscsixst)    {
  241.                       /* it is a SCSI drive */
  242.                     /* set the relative bit, 1 is a SCSI, other is not */
  243.                     typedrv |= setmask << dev;
  244.                     /* set the relative bit, 1 is a removable */
  245.                     typedev |= setmask << dev;
  246.                 } else {
  247.                     ;            /* don't set the SCSI bit */
  248.                 }
  249.             /*    Jul 15, 93 jye: consider the Mega STE which is also a use the 
  250.                 scsi drive under the acsi bus, in this case, we need set the
  251.                 'typedrv', if so, the bug that can't format the unit 0 will be
  252.                 killed. If the 'inqret' = OK, this means they drive is SCSI
  253.                 drive.
  254.             } else if (dev > 7)    {
  255.             */
  256.             } else    {
  257.                   /* it is a SCSI drive, because inqret = OK */
  258.                 /* set the relative bit, 1 is a SCSI, other is not */
  259.                 typedrv |= setmask << dev;
  260.             }
  261.         }
  262.         if ((ret = getroot(dev, buf, (SECTOR)0)) < 0) {
  263.             if (!fnp)  rangelog(dev);
  264.             continue;
  265.         } else {        /* ret >= 0 */
  266.             if (ret > 0) {
  267.                 if ((flag) && (tsterr(ret) == OK))    {    
  268.                 /* if non-0, report error if medium changed */
  269.                         erasemsg();
  270.                         /* Jul-23-93 jye: Fixed this bug that we should conti-
  271.                            nue scan the rest drives. So delet this 2 lines
  272.  
  273.                         slwacsi = 0;
  274.                          return ERROR;
  275.  
  276.                         */
  277.                         continue;
  278.                 }
  279.                 if ((ret = getroot(dev, buf, (SECTOR)0))) {    /* try again */
  280.                     if (ret > 0 && flag && tsterr(ret) == OK)    {
  281.                         erasemsg();
  282.                         /* Jul-23-93 jye: Fixed this bug that we should conti-
  283.                            nue scan the rest drives. So delet this 2 lines
  284.  
  285.                         slwacsi = 0;
  286.                          return ERROR;
  287.  
  288.                         */
  289.                         continue;
  290.                     } else if ((ret > 0) && (!flag))    {
  291.                         if (((inqret == OK)||(inqret == 7)) && 
  292.                                              (sendata[1] & mask))    { 
  293.                             /* it is a removable drive */
  294.                             /* but forget insert the cartridge */
  295.                             err(instdrv);
  296.                                ostack = Super(NULL);
  297.                                delay();
  298.                             /* unlock the floptical drive */
  299.                             mdsense(dev, 0x2e, 0, 42, buf);    
  300.                                delay();
  301.                                Super(ostack);
  302.                             /* set the relative bit, 1 is a removable */
  303.                             typedev |= setmask << dev;
  304.                         }
  305.                         /*
  306.                         if (fnp == 1)    {  do format 
  307.                             livedevs[dev] = 1;
  308.                             if (dev < 8)  there is a ACSI in the system 
  309.                                 noacsi = 0;
  310.                             yesscan = 1;
  311.                         }
  312.                         */
  313.                     }
  314.                     if (!fnp)    {
  315.                         rangelog(dev);
  316.                     }
  317.                     continue;
  318.                 }
  319.             }
  320.             if ((inqret == OK)||(inqret == 7))     {  /* it is a SCSI drive */
  321.                 if (sendata[1] & mask)    { /* it is a removable drive */
  322.                     /* set the relative bit, 1 is a removable, other is not */
  323.                     typedev |= setmask << dev;
  324.                        ostack = Super(NULL);
  325.                        delay();
  326.                     /* unlock the floptical drive */
  327.                     mdsense(dev, 0x2e, 0, 42, buf);    
  328.                        delay();
  329.                        Super(ostack);
  330.                 }
  331.             }
  332.     atst:
  333.             if (dev < 8)    {    /* there is a ACSI drive in the system */
  334.                 noacsi = 0;
  335.             }
  336.             livedevs[dev] = 1;
  337.             yesscan = 1;
  338.             if (stgpart(dev, buf, (PART *)&partinfo) == ERROR)    {
  339.                 erasemsg();
  340.                 slwacsi = 0;
  341.                 return ERROR;
  342.             }
  343.             if (ext != NO_EXT)    {
  344.                 sortpart(partinfo,SCAN_BS); 
  345.             }
  346.         for (partno = 0; partno < npart; ++partno) {
  347.             if ((partinfo[partno].p_flg & P_EXISTS) &&
  348.                 (partinfo[partno].p_siz != (SECTOR)0) &&
  349.                 (((partinfo[partno].p_id[0] == 'G') &&
  350.                  (partinfo[partno].p_id[1] == 'E') &&
  351.                  (partinfo[partno].p_id[2] == 'M'))   ||
  352.                  ((partinfo[partno].p_id[0] == 'B') &&
  353.                  (partinfo[partno].p_id[1] == 'G') &&
  354.                  (partinfo[partno].p_id[2] == 'M'))))   
  355.             {
  356.                 if (nlogdevs > EXTRALOGD)    {
  357.                     continue;
  358.                 }
  359.                 logmap[nlogdevs].lm_physdev = dev;
  360.                 logmap[nlogdevs].lm_partno = partno;
  361.                 logmap[nlogdevs].lm_start =  partinfo[partno].p_st;
  362.                 logmap[nlogdevs].lm_siz =      partinfo[partno].p_siz;
  363.                 ++nlogdevs;
  364.                 if (nlogdevs == MAXLOGDEVS)         {
  365.                     showmany = 1;
  366.                 }
  367.             }
  368.         }
  369.     }
  370.     inipart(partinfo, npart);
  371.     if (partinfo > 0)    Mfree(partinfo);
  372.     }
  373.  
  374. noidedr:
  375.     if ((maxloop > 16) && ((ttscsi)||(spscsixst)))    {
  376.         maxloop = 16;
  377.         dev = 8;
  378.         slwacsi = 0;
  379.         if (spscsixst)    {
  380.             slwacsi = 1;
  381.         }
  382.         goto rerescan;
  383.     } else if (((maxloop > 16) && ((!ttscsi)&&(!spscsixst))) 
  384.                                || ((ttscsi)&&(maxloop>8)))    {
  385.         maxloop = 8;
  386.         dev = 0;
  387.         slwacsi = 1;
  388.         goto rerescan;
  389.     }
  390.     erasemsg();
  391.     slwacsi = 0;
  392.     return OK;
  393. }
  394.  
  395.  
  396.  
  397. /* get the identification of drive */
  398.  
  399. gdrvid(indx, sptr, dptr)
  400. int indx;
  401. char *sptr;
  402. char *dptr;
  403. {
  404.  
  405.     int i, j=0;
  406.  
  407.     /* string in ptr is sperated by space */
  408.     for (i=0; i < 24; i++)    {
  409.         if ((*dptr++ = *sptr++) == 0x20)    {
  410.             j++;
  411.             if (j > 1)    {
  412.                 dptr--;
  413.             }
  414.         } else {
  415.             j = 0;
  416.         }
  417.     }
  418.     *(dptr-1) = 0;
  419.     /*
  420.     while ((*sptr != 0x20) && (*sptr))    {
  421.         *dptr++ = *sptr++;
  422.     }
  423.     *dptr++ = 0x20;
  424.     sptr = ptr+8;
  425.     while ((*sptr != 0x20) && (*sptr))    {
  426.         *dptr++ = *sptr++;
  427.     }
  428.     *dptr = 0;
  429.     */
  430. }
  431.  
  432.  
  433. /* rerange the partition informations. */
  434.  
  435.  sortpart(pinfo, type)
  436.  PART *pinfo;
  437.  int type;                /* USER_ED = 1: for user interface use */
  438.                          /* SCAN_BS = 0: for rescan() and laybs() use */
  439.  {
  440.      int i, j, k;
  441.     PART rpart[2];
  442.  
  443.     if (ext == NO_EXT) return OK;    /* don't need sort */
  444.     for (i = 0; i < 2; i++)    { /* initialize the temple space */
  445.         rpart[i].p_flg = 0L;
  446.         rpart[i].p_st = 0L;
  447.         rpart[i].p_siz = 0L;
  448.         for (k = 0; k < 3; k++)
  449.             rpart[i].p_id[k] = '0';
  450.     }
  451.     /* save the partitions that after the extened partitions */
  452.     for (i = ext+1, j=0; i < 4; i++, j++)        {
  453.         if (pinfo[i].p_flg & P_EXISTS)    {
  454.             rpart[j].p_flg = P_EXISTS;
  455.             rpart[j].p_st = pinfo[i].p_st;
  456.             rpart[j].p_siz = pinfo[i].p_siz;
  457.             for (k = 0; k < 3; k++)
  458.                 rpart[j].p_id[k] = pinfo[i].p_id[k];
  459.         } 
  460.     }
  461.     /* move the extened partition to the front */
  462.      for (i=4, j = ext; i < npart; i++, j++)    {
  463.         if (pinfo[i].p_flg & P_EXISTS)    {
  464.             pinfo[j].p_flg = P_EXISTS;
  465.             pinfo[j].p_st = (type)?(pinfo[i].p_st):(pinfo[i].p_st + ROOTSECT);
  466.             pinfo[j].p_siz = (type)?(pinfo[i].p_siz):(pinfo[i].p_siz-ROOTSECT);
  467.             for (k = 0; k < 3; k++)
  468.                 pinfo[j].p_id[k] = pinfo[i].p_id[k];
  469.         } else { j--;}    /* stay with that space */
  470.     }
  471.     /* copy the not extended partitions back after the extended partitions */
  472.      for (i=0; i < 2; i++, j++)    {
  473.         if (rpart[i].p_flg & P_EXISTS)    {
  474.             pinfo[j].p_flg = P_EXISTS;
  475.             pinfo[j].p_st = rpart[i].p_st;
  476.             pinfo[j].p_siz = rpart[i].p_siz;
  477.             for (k = 0; k < 3; k++)
  478.                 pinfo[j].p_id[k] = rpart[i].p_id[k];
  479.         } else {j--;}
  480.     }
  481.     for (i = j; i < npart; i++)    { /* set the rest to 0 */
  482.         pinfo[i].p_flg = 0L;
  483.         pinfo[i].p_st = 0L;
  484.         pinfo[i].p_siz = 0L;
  485.         for (k = 0; k < 3; k++)
  486.             pinfo[i].p_id[k] = '0';
  487.     }
  488. }
  489.  
  490.  
  491. /* 
  492.  * check to find out the exist of device
  493.  */
  494.  
  495. rangelog(dev)
  496.  
  497. int dev;
  498.  
  499. {
  500.     PUNINFO *divinfo;
  501.     int devnum;
  502.  
  503.     ostack = Super(NULL);
  504.     divinfo = ((PUNINFO *) *((long *)(0x516)));
  505.     for (devnum = 0; devnum < MAXUNITS; ++devnum)    {
  506.         if ((int)(divinfo->pun[devnum] & 0x07) == dev)    {
  507.             delay();
  508.             nlogdevs++;
  509.         }
  510.     }
  511.     Super(ostack);
  512. }
  513.  
  514. /*
  515.  * From a PHYSICAL device unit (0->7)
  516.  * and a partition number (0->3), figure
  517.  * out the LOGICAL disk number ('C'->'P').
  518.  *
  519.  * return the LOGICAL disk number or
  520.  * ERROR if the PHYSICAL device doesn't exist.
  521.  *
  522.  */
  523. phys2log(pdev, pno)
  524. int  pdev;    /* physical device unit */
  525. int  pno;    /* partition number (0 -> 3) */
  526. {
  527.     int logdev;        /* index to step through partitions of a phys unit */
  528.  
  529.     for (logdev = 0; logdev < EXTRALOGD; logdev++) {
  530.         if (logmap[logdev].lm_physdev == pdev &&
  531.             logmap[logdev].lm_partno == pno)
  532.             return ('C'+logdev);
  533.     }
  534.     return ERROR;
  535. }
  536.  
  537.  
  538. /*
  539.  * Map block on logical device to
  540.  * block on physical device;
  541.  * return ERROR if the logical device
  542.  * doesn't exist.
  543.  */
  544. log2phys(adev, ablk)
  545. int *adev;
  546. SECTOR *ablk;
  547. {
  548.     int dev;
  549.     char xbuf[256];
  550.     
  551.     dev = *adev;
  552.     if (dev >= 0 && dev <= 17)
  553.     return OK;
  554.  
  555.     dev = toupper(dev);
  556.     if (dev >= 'C' && dev <= 
  557.                 ('C'+EXTRALOGD)) /* from C to 't' are 50 logic device */
  558.     {
  559.     dev -= 'C';
  560.     *adev = logmap[dev].lm_physdev;
  561.     *ablk = logmap[dev].lm_start + *ablk;
  562.     return OK;
  563.     }
  564.  
  565.     return ERROR;
  566. }
  567.  
  568.  
  569.  
  570. /*
  571.  * Return physical starting block# of a partition
  572.  *
  573.  */
  574. SECTOR 
  575. logstart(ldev)
  576. int ldev;    /* logical device */
  577. {
  578.     ldev = toupper(ldev);
  579.     if (ldev >= 'C' && ldev <= 
  580.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  581.         ldev -= 'C';
  582.         return (logmap[ldev].lm_start);
  583.     }
  584.     return ERROR;
  585. }
  586.  
  587.  
  588.  
  589. /*
  590.  * Return physical starting block# of a partition's data block.
  591.  *
  592.  */
  593. SECTOR 
  594. logend(ldev)
  595. int ldev;    /* logical device */
  596. {
  597.     ldev = toupper(ldev);
  598.     if (ldev >= 'C' && ldev <= 
  599.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  600.         ldev -= 'C';
  601.         return (logmap[ldev].lm_start+logmap[ldev].lm_siz-1);
  602.     }
  603.     return ERROR;
  604. }
  605.  
  606.  
  607. #define    MFM 17        /* sectors per track for MFM */
  608. #define    RLL 26        /* sectors per track for RLL */
  609.  
  610.  
  611. /*
  612.  * Check if dev's root block is intact.
  613.  * Return number of sectors per track on disk.
  614.  *
  615.  */
  616. chkroot(dev, bs)
  617. int dev;
  618. char *bs;
  619. {
  620.     extern long get3bytes();
  621.     extern long get4bytes();
  622.     SETMODE *mb;
  623.     int i, ret, set, scsidrv, mask=0x0001;
  624.     int page=4, bsiz;
  625.     int head, spt;
  626.     SECTOR size, msiz, cyl;    /* size of media */
  627.     char buf[512], sendata[32];
  628.     long dmaptr, tmpptr;
  629.     char *dmahigh=0xffff8609,
  630.          *dmamid=0xffff860b,
  631.          *dmalow=0xffff860d;
  632.     
  633.     size = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  634.     
  635.     ret = OK;
  636.     if (dev == 16)    {        /* it is a IDE-AT drive */
  637.         msiz = (SECTOR)athead * (SECTOR)atcyl * (SECTOR)atspt;
  638.         if (size != msiz)
  639.             ret = ERROR;
  640.         return(ret);
  641.     } else if (dev > 7)    {    /* it is a scsi drive */
  642.         ostack = Super(NULL);
  643.         delay();
  644.         if ((ret = readcap(dev, 0, (long)0, sendata)) == OK) {
  645.             if (msiz = get4bytes(sendata))    {
  646.                 msiz += 1;
  647.                 delay();
  648.                 Super(ostack);
  649.                 goto chkend;
  650.             } 
  651.         } 
  652.         for (i = 0; i < 32; i++)
  653.             sendata[i] = 0;
  654.         if ((ret = mdsense(dev, 4, 0, 32, sendata)) == OK)    {
  655.             if((msiz=get3bytes(sendata+5)))    {
  656.                         delay();
  657.                         Super(ostack);
  658.                         goto chkend;
  659.             }
  660.         }
  661.         for (i = 0; i < 32; i++)
  662.             sendata[i] = 0;
  663.         if ((ret = mdsense(dev, 0, 0, 16, sendata)) == OK)    {
  664.             if((msiz=get3bytes(sendata+5)))    {
  665.                         delay();
  666.                         Super(ostack);
  667.                         goto chkend;
  668.             }
  669.         }
  670.         for (i = 0; i < 32; i++)
  671.             sendata[i] = 0;
  672.         if ((ret = mdsense(dev, 3, 0, 32, sendata)) == OK)    {
  673.             if((msiz=get3bytes(sendata+5)))    {
  674.                         delay();
  675.                         Super(ostack);
  676.                         goto chkend;
  677.             }
  678.         }
  679.         msiz = size;
  680.         delay();
  681.         Super(ostack);
  682.         goto chkerr;
  683.     }
  684.  
  685.     ostack = Super(NULL);
  686.     /* Get format parameters/ disk size from media */
  687.     set = typedev & (mask << dev);
  688.     scsidrv = typedrv & (mask << dev);
  689.     bsiz = ((set) || (scsidrv)) ? (16) : (22);
  690.     if ((set) || (scsidrv))    {
  691.         for (i = 0; i < 32; i++)
  692.             sendata[i] = 0;
  693.         mdsense(dev, 0, 0, bsiz, sendata);
  694.         if((msiz=get3bytes(sendata+5)))    {
  695.                     delay();
  696.                     Super(ostack);
  697.                     goto chkend;
  698.         }
  699. redopg:
  700.         for (i = 0; i < 32; i++)
  701.             sendata[i] = 0;
  702.         ret = mdsense(dev, page, 0, 32, sendata);/* use page code 4, but get */
  703.                                             /* info from the mdsense header */
  704.         for (i = 0; i < 32; i++)
  705.             if (sendata[i])
  706.                 break;
  707.         if ((i==32) && (page == 4))        {
  708.             page = 3;
  709.             goto redopg;
  710.         } else if (i == 32)    {
  711.             msiz = size;
  712.             delay();
  713.             Super(ostack);
  714.             goto chkend;
  715.         }
  716.         if (!(msiz = get3bytes(sendata+5)))    {
  717.             if (page == 4)    {
  718.                 page = 3;
  719.                 /*
  720.                 cyl = get3bytes(sendata+14);
  721.                 head = *(sendata+17);
  722.                 */
  723.                 goto redopg;
  724.             } else {
  725.                 /*
  726.                 spt = getword(sendata+22);
  727.                 msiz = cyl * head * spt;
  728.                 */
  729.                 msiz = size;
  730.             }
  731.         }
  732.         delay();
  733.         Super(ostack);
  734.         goto chkend;
  735.     } else    {
  736.         ret = mdsense(dev, 0, 0, 22, sendata);
  737.         delay();
  738.         Super(ostack);
  739.  
  740.         /* If full SCSI, will return number of blocks */
  741.         /* on disk at byte 5, 6 and 7.  If Adaptec,   */
  742.         /* will return 0 for number of blocks on disk */
  743.         /* on SCSI. */
  744.  
  745.             if (!(msiz = get3bytes(sendata+5))) {    /* no disk size returned? */
  746.             /* Yup, ie., it's adaptec's.  Interpret as SETMODE structure */
  747.             mb = (SETMODE *)sendata;
  748.             /* get number of cylinders */
  749.             cyl = mb->smd_cc[0];
  750.             cyl <<= 8;
  751.             cyl |= mb->smd_cc[1];
  752.     
  753.             /* get number of heads */
  754.             head = mb->smd_dhc;
  755.     
  756.             msiz = (SECTOR)head * (SECTOR)cyl * MFM;
  757.     
  758.             for (i = 0; i < 20; i++) {
  759.                 if ((ret = rdsects(dev, 1, buf, msiz+i)) == OK) {
  760.                     /* find out whether data has been transferred, by
  761.                           checking if dma pointer has been moved.      */
  762.  
  763.                     ostack = Super(NULL);
  764.                     delay();
  765.                     dmaptr = *dmahigh;
  766.                     dmaptr &= 0x0000003f;
  767.                     dmaptr <<= 16;
  768.                     tmpptr = *dmamid;
  769.                     tmpptr &= 0x000000ff;
  770.                     tmpptr <<= 8;
  771.                     dmaptr |= tmpptr;
  772.                     tmpptr = *dmalow;
  773.                     tmpptr &= 0x000000ff;
  774.                     dmaptr |= tmpptr;
  775.                     delay();
  776.                     Super(ostack);
  777.  
  778.                     if (dmaptr != buf)
  779.                         break;
  780.                    } else {            /* rdsects return an error */
  781.                     if (tsterr(ret) == OK) {
  782.                            break;
  783.                     }
  784.                 }
  785.             }
  786.     
  787.             if (ret == MDMCHGD)        /* check if error occurred */
  788.                 return (ret);
  789.        
  790.             /* Determine if media is MFM or RLL */
  791.             if (i < 20)    {
  792.                 msiz = (SECTOR)head * (SECTOR)cyl * RLL;
  793.             }
  794.             goto chkend;
  795.         }
  796.     }
  797. chkerr:
  798.     if (ret != 0) {
  799.         ret = errcode(dev);
  800.         if (tsterr(ret) != OK) 
  801.             return ERROR;
  802.         return (-3);    /* don't have to show the alert box */
  803.     }
  804. chkend:
  805.     if (size != msiz)
  806.         ret = ERROR;
  807.     else 
  808.         ret = OK;
  809.         
  810.     return (ret);
  811. }
  812.  
  813. /*
  814.  * Chkparm()
  815.  *    Check if given logical device has the asssumed parameters.
  816.  * Assumptions are:
  817.  *    - 512 bytes/sector
  818.  *    - 2 sectors/cluster
  819.  *    - 1 reserved sector
  820.  *    - 2 FATs
  821.  *
  822.  * Input:
  823.  *    ldev - logical device number ('C' -> 'P').
  824.  *
  825.  * Return:
  826.  *    OK - parameters of partition match the assumptions
  827.  *    ERROR - something went wrong.
  828.  *
  829.  * Comment:
  830.  *    Number of FATs is assumed to be 2.  Cannot check this 
  831.  * because previous version of HDX did not put that in the boot
  832.  * sector.
  833.  */
  834. chkparm(ldev)
  835. int ldev;
  836. {
  837.     char bs[512];        /* boot sector */
  838.     BOOT *boot;            /* boot structure */
  839.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  840.     int ret;
  841.  
  842.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  843.         if (tsterr(ret) != OK)
  844.             err(bootread);
  845.         ret = ERROR;
  846.         goto parmend;
  847.     }    
  848.  
  849.     boot = (BOOT *)bs;
  850.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  851.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  852.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  853.     if (bps % BPS            /* bytes per sector == ratio of 512 ? */
  854.     || res != 1) {            /* num sectors reserved == 1 ? */
  855.     ret = ERROR;            /* Nope, different from assumptions */
  856.     goto parmend;
  857.     }
  858.     
  859.     /* Check if sectors per cluster make sense */
  860.     if (boot->b_spc != 2) {
  861.         ret = ERROR;
  862.         goto parmend;
  863.     }
  864.     
  865.     ret = OK;                /* If yes, return OK */
  866.  
  867. parmend:
  868.     return ret;
  869. }
  870.  
  871.  
  872. ichkparm(ldev)
  873. int ldev;
  874. {
  875.     char bs[512];        /* boot sector */
  876.     BOOT *boot;            /* boot structure */
  877.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  878.     int ret;
  879.  
  880.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  881.         if (tsterr(ret) != OK)
  882.             err(bootread);
  883.         ret = ERROR;
  884.         goto parmend;
  885.     }    
  886.  
  887.     boot = (BOOT *)bs;
  888.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  889.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  890.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  891.     if (bps != 512            /* bytes per sector == 512 ? */
  892.     || res != 1) {            /* num sectors reserved == 1 ? */
  893.     ret = ERROR;            /* Nope, different from assumptions */
  894.     goto parmend;
  895.     }
  896.     
  897.     /* Check if sectors per cluster make sense */
  898.     if ((siz >= 0x8000L && boot->b_spc != 4) ||
  899.         (siz < 0x8000L && boot->b_spc != 2)) {
  900.         ret = ERROR;
  901.         goto parmend;
  902.     }
  903.     
  904.     ret = OK;                /* If yes, return OK */
  905.  
  906. parmend:
  907.     return ret;
  908. }
  909.  
  910.  
  911. /*
  912.  * Get dev's root block.
  913.  *
  914.  */
  915. getroot(dev, buf, sect)
  916. int dev;
  917. char *buf;
  918. SECTOR sect;
  919. {
  920.     return rdsects(dev, 1, buf, sect);
  921. }
  922.  
  923.  
  924. /*
  925.  * Put dev's root block.
  926.  *
  927.  */
  928. putroot(dev, buf, sect)
  929. int dev;
  930. char *buf;
  931. SECTOR sect;
  932. {
  933.     return wrsects(dev, 1, buf, sect);
  934. }
  935.  
  936.  
  937. /*
  938.  *  Read sector(s) from dev.
  939.  *
  940.  *  Input:
  941.  *    dev - device number (logical or physical).
  942.  *    num - number of sectors to read.
  943.  *    buf - buffer to write data read.
  944.  *    sect - starting sector number to read from.
  945.  *
  946.  *  Return:
  947.  *    errnum - 0: if read is successful.
  948.  *         an error code: if read is unsuccessful.
  949.  */
  950. rdsects(dev, num, buf, sect)
  951. int dev;            /* device number (logical or physical) */
  952. UWORD num;            /* number of sectors to read */
  953. char *buf;
  954. SECTOR sect;            /* starting sector to read from */
  955. {
  956.     int errnum;
  957.  
  958.     if (log2phys(&dev, §) < 0)
  959.     return ERROR;
  960.  
  961.     ostack = Super(NULL);
  962.     if (dev == 16)    { /* it is a AT drive */
  963.         /*
  964.         if (!(athead*atspt*sect))    {
  965.             formaterr(dev);
  966.             errnum = ERROR;
  967.         } else {
  968.             errnum = ideread(athead, atspt, sect, num, buf, (UWORD)dev);
  969.         }
  970.         */
  971.         errnum = ideread(athead, atspt, sect, num, buf, (UWORD)dev);
  972.     } else {
  973.         /*
  974.         if (spscsixst)    {
  975.             resetspscsi();
  976.         }
  977.         */
  978.         errnum = hread(sect, num, buf, (UWORD)dev);
  979.     }
  980.     /*
  981.     if (errnum == 04)    {      the drive is stop 
  982.         delay();
  983.         stunt();
  984.         delay();
  985.         errnum = hread(sect, num, buf, (UWORD)dev);
  986.     }
  987.     */
  988.     delay();
  989.     Super(ostack);
  990.  
  991.     if (errnum > 0) {
  992.         errnum = errcode(dev);
  993.     }
  994.         
  995.     return errnum;        /* return the error code */
  996. }
  997.  
  998.  
  999. /*
  1000.  *  Write sector(s) to dev.
  1001.  *
  1002.  *  Input:
  1003.  *    dev - device number (logical or physical).
  1004.  *    num - number of sectors to write.
  1005.  *    buf - buffer with data to be written.
  1006.  *    sect - starting sector number to write to.
  1007.  *
  1008.  *  Return:
  1009.  *    errnum - 0: if write is successful.
  1010.  *         an error code: if write is unsuccessful.
  1011.  */
  1012. wrsects(dev, num, buf, sect)
  1013. int dev;            /* device number (logical or physical */
  1014. UWORD num;            /* number of sectors to write */
  1015. char *buf;            /* buffer with data to be written */
  1016. SECTOR sect;            /* starting sector to write to */
  1017. {
  1018.     int errnum;
  1019.  
  1020.     if (log2phys(&dev, §) < 0)
  1021.     return ERROR;
  1022.  
  1023.     ostack = Super(NULL);
  1024.     if (dev == 16)    { /* it is a AT drive */
  1025.         /*
  1026.         if (!(athead*atspt*sect))    {
  1027.             formaterr(dev);
  1028.             errnum = ERROR;
  1029.         } else {
  1030.             errnum = idewrite(athead, atspt, sect, num, buf, (UWORD)dev);
  1031.         }
  1032.         */
  1033.         errnum = idewrite(athead, atspt, sect, num, buf, (UWORD)dev);
  1034.     } else {
  1035.         errnum = hwrite(sect, num, buf, (UWORD)dev);
  1036.     }
  1037.     delay();
  1038.     Super(ostack);
  1039.  
  1040.     if (errnum > 0) {
  1041.         errnum = errcode(dev);
  1042.     }
  1043.     return errnum;
  1044. }
  1045.  
  1046.  
  1047. /*
  1048.  * Zero range of sectors on dev.
  1049.  *
  1050.  */
  1051. zerosect(dev, start, count)
  1052. int dev;
  1053. SECTOR start;
  1054. UWORD count;
  1055. {
  1056.     char *zbuf;
  1057.     int  v;
  1058.     UWORD i;
  1059.  
  1060.     if ((zbuf = (char *)mymalloc(ZBUFSIZ)) <= 0)
  1061.         return err(nomemory);
  1062.         
  1063.     if (log2phys(&dev, &start) < 0) {
  1064.         free(zbuf);
  1065.     return ERROR;
  1066.     }
  1067.  
  1068.     fillbuf(zbuf, (long)ZBUFSIZ, 0L);
  1069.  
  1070.     while (count)
  1071.     {
  1072.         if (count > ZCOUNT)
  1073.             i = ZCOUNT;
  1074.         else i = count;
  1075.  
  1076.     if ((v = wrsects(dev, i, zbuf, start)) != 0)
  1077.         break;
  1078.     start += i;
  1079.     count -= i;
  1080.     }
  1081.     free(zbuf);
  1082.     
  1083.     return v;
  1084. }
  1085.